package com.hexingmo.dawn.lang.concurrent;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;
import java.util.Objects;

/**
 * 可配置的线程工厂实现，支持自定义线程的各种属性。
 *
 * <p>该类提供了灵活的配置选项，包括线程名称、守护线程状态、线程优先级、
 * 未捕获异常处理器、线程组、上下文类加载器和栈大小等。通过配置这些属性，
 * 可以创建满足特定需求的线程。</p>
 *
 * <p><strong>特性：</strong></p>
 * <ul>
 *   <li><strong>灵活配置</strong>：支持所有主要的线程属性配置</li>
 *   <li><strong>线程安全</strong>：使用原子计数器确保线程名称唯一性</li>
 *   <li><strong>参数验证</strong>：内置参数验证，确保配置的有效性</li>
 *   <li><strong>默认值支持</strong>：提供合理的默认配置，减少配置代码</li>
 *   <li><strong>高性能</strong>：优化的线程创建逻辑</li>
 * </ul>
 *
 * <p><strong>使用示例：</strong></p>
 * <pre>{@code
 * // 基本使用
 * ConfigurableThreadFactory factory = new ConfigurableThreadFactory()
 *     .setNameFormat("worker-%d")
 *     .setDaemon(true)
 *     .setPriority(Thread.MAX_PRIORITY)
 *     .setStackSize(1024 * 1024); // 1MB栈大小
 *
 * // 创建线程
 * Thread thread = factory.newThread(() -> {
 *     // 线程执行逻辑
 * });
 * }</pre>
 *
 * <p><strong>实际应用场景：</strong></p>
 * <ul>
 *   <li><strong>线程池配置</strong>：为不同的线程池创建具有特定配置的线程</li>
 *   <li><strong>性能调优</strong>：根据业务需求调整线程优先级和栈大小</li>
 *   <li><strong>内存管理</strong>：通过控制栈大小优化内存使用</li>
 *   <li><strong>类加载控制</strong>：通过contextClassLoader控制类的加载上下文</li>
 *   <li><strong>监控集成</strong>：通过线程命名和异常处理器集成监控系统</li>
 * </ul>
 *
 * @author He Xing Mo
 * @since 1.0
 * @see ThreadFactory
 * @see Thread
 * @see ThreadGroup
 * @see ClassLoader
 */
public class ConfigurableThreadFactory implements ThreadFactory {

    /**
     * 线程名称格式，支持 %d 占位符表示线程编号。
     * 如果为null，则使用默认的线程命名策略。
     * 例如："worker-%d" 会生成 "worker-1", "worker-2" 等名称。
     */
    private String nameFormat;

    /**
     * 是否为守护线程的标志。
     * 如果为null，则保持线程原有的守护状态。
     * 如果为true，创建的线程将是守护线程；如果为false，创建的线程将是用户线程。
     */
    private Boolean daemon;

    /**
     * 线程优先级，范围从 {@link Thread#MIN_PRIORITY} 到 {@link Thread#MAX_PRIORITY}。
     * 如果为null，则保持线程原有的优先级。
     * 优先级越高，线程在竞争CPU资源时越有优势。
     */
    private Integer priority;

    /**
     * 未捕获异常处理器，用于处理线程中发生的未捕获异常。
     * 如果为null，则使用默认的异常处理行为。
     * 当线程中抛出未捕获的异常时，该处理器会被调用。
     */
    private Thread.UncaughtExceptionHandler uncaughtExceptionHandler;

    /**
     * 线程组，用于管理线程的集合。
     * 如果为null，则使用当前线程的线程组。
     * 线程组可以统一设置线程的安全策略，便于线程管理和监控。
     */
    private ThreadGroup threadGroup;

    /**
     * 上下文类加载器，用于控制线程中类的加载上下文。
     * 如果为null，则使用当前线程的上下文类加载器。
     * 这对于插件架构和模块化应用特别有用。
     */
    private ClassLoader contextClassLoader;

    /**
     * 线程栈大小，以字节为单位。
     * 如果为null或0，则使用JVM默认的栈大小。
     * 较小的栈大小可以节省内存，较大的栈大小适合深度递归。
     */
    private Long stackSize;

    /**
     * 线程计数器，用于生成唯一的线程名称。
     */
    private final AtomicLong threadCounter = new AtomicLong(0);

    /**
     * 默认构造函数，创建使用默认配置的线程工厂。
     */
    public ConfigurableThreadFactory() {
        // 使用默认值
    }

    /**
     * 设置线程名称格式。
     *
     * <p>名称格式支持 {@code %d} 占位符，该占位符会被线程编号替换。
     * 如果不设置名称格式，线程将保持原有的名称。</p>
     *
     * <p><strong>格式示例：</strong></p>
     * <ul>
     *   <li><strong>"worker-%d"</strong>：生成 worker-1, worker-2, worker-3...</li>
     *   <li><strong>"pool-%d-thread-%d"</strong>：生成 pool-1-thread-1, pool-1-thread-2...</li>
     *   <li><strong>"custom-name"</strong>：所有线程都使用相同的名称</li>
     * </ul>
     *
     * @param nameFormat 线程名称格式，支持 %d 占位符
     * @return 当前线程工厂实例，支持链式调用
     * @throws IllegalArgumentException 如果nameFormat为null或空
     */
    public ConfigurableThreadFactory setNameFormat(String nameFormat) {
        if (nameFormat == null || nameFormat.trim().isEmpty()) {
            throw new IllegalArgumentException("Name format cannot be null or empty");
        }
        this.nameFormat = nameFormat.trim();
        return this;
    }

    /**
     * 设置是否为守护线程。
     *
     * <p>守护线程是JVM中的特殊线程，当所有非守护线程结束时，JVM会自动退出。
     * 如果不设置，线程将保持原有的守护状态。</p>
     *
     * @param daemon 是否为守护线程
     * @return 当前线程工厂实例，支持链式调用
     */
    public ConfigurableThreadFactory setDaemon(boolean daemon) {
        this.daemon = daemon;
        return this;
    }

    /**
     * 设置线程优先级。
     *
     * <p>线程优先级决定了线程在竞争CPU资源时的相对重要性。
     * 如果不设置，线程将保持原有的优先级。</p>
     *
     * <p><strong>优先级范围：</strong></p>
     * <ul>
     *   <li><strong>{@link Thread#MIN_PRIORITY}</strong>：最低优先级（1）</li>
     *   <li><strong>{@link Thread#NORM_PRIORITY}</strong>：普通优先级（5）</li>
     *   <li><strong>{@link Thread#MAX_PRIORITY}</strong>：最高优先级（10）</li>
     * </ul>
     *
     * @param priority 线程优先级
     * @return 当前线程工厂实例，支持链式调用
     * @throws IllegalArgumentException 如果priority超出有效范围
     */
    public ConfigurableThreadFactory setPriority(int priority) {
        if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
            throw new IllegalArgumentException(
                    String.format("Thread priority must be between %d and %d, got %d",
                            Thread.MIN_PRIORITY, Thread.MAX_PRIORITY, priority));
        }
        this.priority = priority;
        return this;
    }

    /**
     * 设置未捕获异常处理器。
     *
     * <p>当线程中发生未捕获的异常时，该处理器会被调用。
     * 如果不设置，使用默认的异常处理行为。</p>
     *
     * @param uncaughtExceptionHandler 未捕获异常处理器
     * @return 当前线程工厂实例，支持链式调用
     */
    public ConfigurableThreadFactory setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {
        this.uncaughtExceptionHandler = uncaughtExceptionHandler;
        return this;
    }

    /**
     * 设置线程组。
     *
     * <p>线程组用于管理线程的集合，可以统一设置线程的安全策略。
     * 如果不设置，使用当前线程的线程组。</p>
     *
     * @param threadGroup 线程组
     * @return 当前线程工厂实例，支持链式调用
     */
    public ConfigurableThreadFactory setThreadGroup(ThreadGroup threadGroup) {
        this.threadGroup = threadGroup;
        return this;
    }

    /**
     * 设置上下文类加载器。
     *
     * <p>上下文类加载器用于控制线程中类的加载上下文。
     * 这对于插件架构、模块化应用和动态类加载特别有用。
     * 如果不设置，使用当前线程的上下文类加载器。</p>
     *
     * @param contextClassLoader 上下文类加载器
     * @return 当前线程工厂实例，支持链式调用
     */
    public ConfigurableThreadFactory setContextClassLoader(ClassLoader contextClassLoader) {
        this.contextClassLoader = contextClassLoader;
        return this;
    }

    /**
     * 设置线程栈大小。
     *
     * <p>栈大小控制线程执行栈的内存分配，以字节为单位。
     * 较小的栈大小可以节省内存，较大的栈大小适合深度递归算法。
     * 如果设置为null或0，则使用JVM默认的栈大小。</p>
     *
     * <p><strong>注意事项：</strong></p>
     * <ul>
     *   <li>栈大小受JVM参数 {@code -Xss} 限制</li>
     *   <li>不同平台对栈大小的支持可能不同</li>
     *   <li>过小的栈大小可能导致 {@link StackOverflowError}</li>
     * </ul>
     *
     * @param stackSize 线程栈大小（字节），null或0表示使用默认值
     * @return 当前线程工厂实例，支持链式调用
     * @throws IllegalArgumentException 如果stackSize为负数
     */
    public ConfigurableThreadFactory setStackSize(Long stackSize) {
        if (stackSize != null && stackSize < 0) {
            throw new IllegalArgumentException("Stack size cannot be negative: " + stackSize);
        }
        this.stackSize = stackSize;
        return this;
    }

    @Override
    public Thread newThread(Runnable r) {
        if (r == null) {
            throw new IllegalArgumentException("Runnable cannot be null");
        }

        // 确定线程组
        ThreadGroup group = threadGroup != null ? threadGroup : getDefaultThreadGroup();

        // 确定线程名称
        String threadName = generateThreadName();

        // 确定栈大小
        long stackSizeValue = stackSize != null ? stackSize : 0L;

        // 创建线程
        Thread thread = new Thread(group, r, threadName, stackSizeValue);

        // 应用配置
        applyConfiguration(thread);

        return thread;
    }

    /**
     * 生成线程名称。
     *
     * @return 生成的线程名称
     */
    private String generateThreadName() {
        if (nameFormat != null) {
            return String.format(nameFormat, threadCounter.incrementAndGet());
        }
        // 使用默认命名策略
        return "ConfigurableThread-" + threadCounter.incrementAndGet();
    }

    /**
     * 应用线程配置。
     *
     * @param thread 要配置的线程
     */
    private void applyConfiguration(Thread thread) {
        // 设置守护线程状态
        if (daemon != null) {
            thread.setDaemon(daemon);
        }

        // 设置线程优先级
        if (priority != null) {
            thread.setPriority(priority);
        }

        // 设置未捕获异常处理器
        if (uncaughtExceptionHandler != null) {
            thread.setUncaughtExceptionHandler(uncaughtExceptionHandler);
        }

        // 设置上下文类加载器
        if (contextClassLoader != null) {
            thread.setContextClassLoader(contextClassLoader);
        }
    }

    /**
     * 获取默认的线程组。
     *
     * <p>优先使用安全管理器指定的线程组，如果没有则使用当前线程的线程组。</p>
     *
     * @return 默认线程组
     */
    private ThreadGroup getDefaultThreadGroup() {
        SecurityManager securityManager = System.getSecurityManager();
        return (securityManager != null) ?
                securityManager.getThreadGroup() : Thread.currentThread().getThreadGroup();
    }

    // Getter 方法
    public String getNameFormat() { return nameFormat; }
    public Boolean getDaemon() { return daemon; }
    public Integer getPriority() { return priority; }
    public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() { return uncaughtExceptionHandler; }
    public ThreadGroup getThreadGroup() { return threadGroup; }
    public ClassLoader getContextClassLoader() { return contextClassLoader; }
    public Long getStackSize() { return stackSize; }
    public long getThreadCount() { return threadCounter.get(); }

    // 状态检查方法
    public boolean hasNameFormat() { return nameFormat != null; }
    public boolean hasDaemon() { return daemon != null; }
    public boolean hasPriority() { return priority != null; }
    public boolean hasUncaughtExceptionHandler() { return uncaughtExceptionHandler != null; }
    public boolean hasThreadGroup() { return threadGroup != null; }
    public boolean hasContextClassLoader() { return contextClassLoader != null; }
    public boolean hasStackSize() { return stackSize != null; }

    /**
     * 检查是否为空配置（所有配置都是默认值）。
     *
     * @return 如果所有配置都是默认值返回true，否则返回false
     */
    public boolean isEmpty() {
        return nameFormat == null && daemon == null && priority == null &&
                uncaughtExceptionHandler == null && threadGroup == null &&
                contextClassLoader == null && stackSize == null;
    }

    @Override
    public String toString() {
        return "ConfigurableThreadFactory{" +
                "nameFormat='" + nameFormat + '\'' +
                ", daemon=" + daemon +
                ", priority=" + priority +
                ", uncaughtExceptionHandler=" + uncaughtExceptionHandler +
                ", threadGroup=" + threadGroup +
                ", contextClassLoader=" + contextClassLoader +
                ", stackSize=" + stackSize +
                ", threadCount=" + threadCounter.get() +
                '}';
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }

        ConfigurableThreadFactory that = (ConfigurableThreadFactory) obj;
        return Objects.equals(nameFormat, that.nameFormat) &&
                Objects.equals(daemon, that.daemon) &&
                Objects.equals(priority, that.priority) &&
                Objects.equals(uncaughtExceptionHandler, that.uncaughtExceptionHandler) &&
                Objects.equals(threadGroup, that.threadGroup) &&
                Objects.equals(contextClassLoader, that.contextClassLoader) &&
                Objects.equals(stackSize, that.stackSize);
    }

    @Override
    public int hashCode() {
        return Objects.hash(nameFormat, daemon, priority, uncaughtExceptionHandler,
                threadGroup, contextClassLoader, stackSize);
    }
}